#include<iostream>
#include<cstdlib>
#include<cassert>
using namespace std;

namespace code 
{
	class string 
	{
	public:
		//1.默认成员函数
		string(const char* str = "")
			:_size(strlen(str))
		{
			_capacity = _size == 0 ? 4 : _size;
			_str = new char[_capacity + 1];
			strcpy(_str, str);
		}

		~string() 
		{
			delete[]_str;
			_str = nullptr;
			_size = _capacity = 0;
		}

		string(const string& s) 
		{
			string tmp(s._str);
			swap(tmp);
		}

		string& operator=(string& tmp) 
		{
			if (_str != tmp._str) swap(tmp);
			return *this;
		}

		void swap(string& s) 
		{
			std::swap(_str, s._str);
			std::swap(_size, s._size);
			std::swap(_capacity, s._capacity);
		}

		//2.访问
		//2.1C语言风格字符串
		char* c_str() { return _str; }
		//2.2[]访问
		char& operator[](size_t pos) 
		{ 
			assert(pos < _size);
			return _str[pos]; 
		}

		const char& operator[](size_t pos)const
		{
			assert(pos < _size);
			return _str[pos];
		}
		//2.3迭代器访问
		typedef char* iterator;
		typedef const char* const_iterator;

		iterator begin() { return _str; }
		const_iterator begin() const{ return _str; }

		iterator end() { return _str + _size; }
		const_iterator end()const { return _str + _size; }

		//3.容量
		size_t size() const { return _size; }
		size_t capacity()const { return _capacity; }
		void reserve(size_t n) 
		{
			if (n > _capacity) 
			{
				char* tmp = new char[n + 1];
				strcpy(tmp, _str);
				delete _str;
				_str = tmp;
				_capacity = n;
			}
		}

		void resize(size_t n, char ch = '\0')
		{
			if (n < _size) 
			{
				_size = n;
				_str[n] = '\0';
			}
			else 
			{
				if (n > _capacity)reserve(n);
				for (size_t i = _size; i < n; i++) 
					_str[i] = ch;

				_size = n;
				_str[n] = '\0';
			}
		}

		//4.增删改查
		void push_back(const char ch) 
		{
			if (_size + 1 > _capacity)reserve(2 * _capacity);
			_str[_size++] = ch;
			_str[_size] = '\0';
		}

		void append(const char* s) 
		{
			size_t len = strlen(s);
			if (_size + len > _capacity)reserve(_size + len);
			strcpy(_str + _size, s);
			_size += len;
		}

		string& operator +=(const char ch) 
		{
			push_back(ch);
			return *this;
		}

		string& operator +=(const char* s)
		{
			append(s);
			return *this;
		}

		void insert(size_t pos, char ch) 
		{
			assert(pos <= _size);
			if (_size + 1 > _capacity)reserve(2 * _capacity);
			size_t end = _size + 1;
			while (end > pos) 
			{
				_str[end] = _str[end - 1];
				end--;
			}
			_str[pos] = ch;
			_size++;
		}

		void insert(size_t pos, const char* s) 
		{
			assert(pos <= _size);
			size_t len = strlen(s);
			if (_size + len > _capacity)reserve(_size + len);
			size_t end = _size + len;
			while (end > pos + len - 1) 
			{
				_str[end] = _str[end - len];
				end--;
			}
			strncpy(_str + pos, s, len);
			_size += len;
		}

		void erase(size_t pos, size_t len = npos) 
		{
			if (len > _size - pos) 
			{
				_size = pos;
				_str[_size] = '\0';
			}
			else 
			{
				strcpy(_str + pos, _str + pos + len);
				_size -= len;
			}
		}

		void clear() 
		{
			_size = 0;
			_str[_size] = '\0';
		}

		//5.其它功能
		size_t find(size_t pos, const char ch) 
		{
			assert(pos < _size);
			for (size_t i = pos; i < _size; i++) 
				if (ch == _str[i])return i;
			
			return npos;
		}

		size_t find(size_t pos, const char* s)
		{
			assert(pos < _size);
			char* index = strstr(_str + pos, s);
			if (index == NULL)return npos;

			return index - _str;
		}

		string substr(size_t pos, size_t len) 
		{
			assert(pos < _size);
			string tmp;

			size_t n = pos + len;
			if (len > _size - pos) n = _size;

			for (size_t i = pos; i < n; i++)
				tmp += _str[i];

			return tmp;
		}

		//6.比较运算符
		bool operator==(const string& s) { return strcmp(_str, s._str) == 0; }
		bool operator!=(const string& s) { return strcmp(_str, s._str) != 0; }
		bool operator<(const string& s) { return strcmp(_str, s._str) < 0; }
		bool operator<=(const string& s) { return *this < s || *this == s; }
		bool operator>(const string& s) { return !(*this <= s); }
		bool operator>=(const string& s) { return !(*this < s); }

		const static size_t npos;
	private:
		char* _str;
		size_t _size;
		size_t _capacity;
	};

	const  size_t string::npos = -1;

	ostream& operator<<(ostream& _cout, const code:: string& s)
	{
		for (auto ch : s)
			_cout << ch;
		return _cout;
	}

	istream& operator>>(istream& _in, code::string& s)
	{
		s.clear();
		char ch; size_t i = 0;
		char buffer[128];

		ch = _in.get();
		while (ch != ' ' && ch != '\n') 
		{
			buffer[i++] = ch;
			if (i == 127) 
			{
				buffer[127] = '\0';
				s += buffer;
				i = 0;
			}
			ch = _in.get();
		}

		if (i > 0) 
		{
			buffer[i] = '\0';
			s += buffer;
		}

		return _in;
	}

	istream& getline(istream& _in, code::string& s)
	{
		s.clear();
		char ch; size_t i = 0;
		char buffer[128];

		ch = _in.get();
		while (ch != '\n')
		{
			buffer[i++] = ch;
			if (i == 127)
			{
				buffer[127] = '\0';
				s += buffer;
				i = 0;
			}
			ch = _in.get();
		}

		if (i > 0)
		{
			buffer[i] = '\0';
			s += buffer;
		}

		return _in;
	}

	void test_init() 
	{
		string s1("hello world");
		cout << s1<<endl;

		cout <<"s2" << endl;
		string s2(s1);
		cout << s2 << endl;

		cout << "s3" << endl;
		string s3 = s2;
		cout << s3 << endl << endl;
	}

	void test_access() 
	{
		string s1("hello world");
		cout << "c_str()" << endl;
		cout << s1.c_str() << endl << endl;

		cout << "[]" << endl;
		for (int i = 0; i < s1.size(); i++)
			cout << s1[i];
		cout << endl << endl;

		cout << "iterator" << endl;
		auto it = s1.begin();
		while (it != s1.end()) 
		{
			cout << *it;
			it++;
		}
		cout << endl << endl;

		cout << "const_iterator" << endl;
		const string s2("hello world");
		for (auto ch : s2)
			cout << ch;
		cout << endl << endl;
	}

	void test_cap() 
	{
		string s1;
		s1.reserve(6);
		cout << "s1.reserve(6): " << s1.size() << endl;
		s1.resize(8, 'x');
		cout << "s1.resize(8, 'x'):" << s1.size() <<" s1:"<< s1.c_str() << endl;
		s1.resize(4);
		cout << "s1.resize(4):" << s1.size() << " s1:" << s1.c_str() << endl;
	}

	void test_modify() 
	{
		string s1;
		s1.push_back('x');
		cout << "s1.push_back(x):" << s1 << endl;

		s1.append("yyy");
		cout << "s1.append(yyy):" << s1 << endl;

		s1 += 'z';
		cout << "s1.+= z:" << s1 << endl;

		s1 += "zzz";
		cout << "s1.+= zz:" << s1 << endl;

		s1.insert(0,'q');
		cout << "s1.insert(0,q):" << s1 << endl;

		s1.insert(0, "ww");
		cout << "s1.insert(0, ww):" << s1 << endl;

		s1.insert(2, "zz");
		cout << "s1.insert(2, zz):" << s1 << endl;

		s1.erase(0, 2);
		cout << "s1.erase(0, 2):" << s1 << endl;

		s1.erase(4);
		cout << "s1.erase(4):" << s1 << endl;
	}

	void test_other() 
	{
		string s1("abcd");

		size_t index1 = s1.find(0,'c');
		cout << "s1.find(0,c):" << index1 << endl;

		size_t index2 = s1.find(1, 'a');
		cout << "s1.find(1,a):" << index2 << endl;

		size_t index3 = s1.find(0, "abcd");
		cout << "s1.find(0, abcd):" << index3 << endl;

		size_t index4 = s1.find(0, "abcde");
		cout << "s1.find(0, abcd):" << index4 << endl;

		string s2 = s1.substr(0, 3);
		cout << "s1.substr(0, 3):" << s2 << endl;

		string s3 = s1.substr(0, 100);
		cout << "s1.substr(0, 100):" << s3 << endl;
	}

	void test_rel() 
	{
		string s1("123");
		string s2("234");

		cout << "123 < 234: " << (s1 < s2) << endl;
		cout << "123 > 234: " << (s1 > s2) << endl;
		cout << "123 = 234: " << (s1 == s2) << endl;
		cout << "123 <= 234: " << (s1 <= s2) << endl;
		cout << "123 >= 234: " << (s1 >= s2) << endl;
		cout << "123 != 234: " << (s1 != s2) << endl;
	}

	void test_stream() 
	{
		string s1,s2;

		cin >> s1;
		getline(cin, s2);
		
		cout << s1 << endl;
		cout << s2 << endl;

	}
}